package com.smart.home.Application;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.net.NetUtil;
import com.smart.home.annotation.autoFill;
import com.smart.home.constant.RoleConstant;
import com.smart.home.constant.UsersConstant;
import com.smart.home.constant.autoFillConstant;
import com.smart.home.context.UserContext;
import com.smart.home.enumeration.OperationType;
import io.swagger.annotations.ApiModel;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;



import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Component
@Slf4j
@ApiModel ("自动填充切面")
public class AutoFillAspect {

    /**
     * 自动填充
     * 切入点
     */
    @Pointcut( "execution(* com.smart.home.mapper.*.*(..))  && @annotation(com.smart.home.annotation.autoFill)" )
    public void autoFill(){}


    /**
     * 切面逻辑
     * @param joinPoint
     */
     @Before("autoFill()")
    public void doAutoFill(JoinPoint joinPoint){
        log.info("自动填充切面逻辑");

        //获取方法签名后并转换成父类后提取相关信息
        MethodSignature methodSignature =(MethodSignature) joinPoint.getSignature();
        autoFill annotation = methodSignature.getMethod().getAnnotation(autoFill.class);
        OperationType value = annotation.value();

        Object[] args = joinPoint.getArgs();
        if(args.length <= 0 || args == null){
            log.info( "没有参数，无法进行自动填充");
            return;
        }

        Object object = args[0];
        //准备数据
        LocalDateTime creatTime = LocalDateTime.now();
        byte status = 1;
        String statusStr = "ONLINE";

        long workerId = NetUtil.ipv4ToLong(NetUtil.LOCAL_IP)%32;
        Snowflake snowflake = new Snowflake(workerId,1);
        String uuid = String.valueOf(snowflake.nextId());
        Long userId = UserContext.getUserId();





         if (value == OperationType.INSERT) {

            // 单独为每个字段 try-catch，避免一个字段失败导致整体失败
            try {
                Method setUuid = object.getClass().getDeclaredMethod(autoFillConstant.uuid, String.class);
                setUuid.invoke(object, uuid); // 注意：这里第一个参数是实例对象
            } catch (Exception e) {
                log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.uuid);
            }

            try {
                Method setCreatedAt = object.getClass().getDeclaredMethod(autoFillConstant.createdAt, LocalDateTime.class);
                setCreatedAt.invoke(object, creatTime);
            } catch (Exception e) {
                log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.createdAt);
            }

            try {
                Method setUpdatedAt = object.getClass().getDeclaredMethod(autoFillConstant.updatedAt, LocalDateTime.class);
                setUpdatedAt.invoke(object, creatTime);
            } catch (Exception e) {
                log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.updatedAt);
            }

            try {
                Method setStatus = object.getClass().getDeclaredMethod(autoFillConstant.status, Byte.class);
                setStatus.invoke(object, status);
            } catch (Exception e) {
                log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.status);
            }

            try {
                Method setOwnerId = object.getClass().getDeclaredMethod(autoFillConstant.ownerId, Long.class);
                setOwnerId.invoke(object, userId);
            }catch (Exception e){
                log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.ownerId);
            }

            //家庭成员


            try {
                Method setUserId = object.getClass().getDeclaredMethod(autoFillConstant.userId, Long.class);
                setUserId.invoke(object, userId);
            }catch (Exception e){
                log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.userId );
            }

            try {
                Method setJoinedAt = object.getClass().getDeclaredMethod(autoFillConstant.joinedAt, LocalDateTime.class);
                setJoinedAt.invoke(object, creatTime);
            }catch (Exception e){
                log.info("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.joinedAt);
            }

            try {
                Method setStatus = object.getClass().getDeclaredMethod(autoFillConstant.status, String.class);
                setStatus.invoke(object, statusStr);
            }catch (Exception e){
                log.info("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.joinedAt);
            }


            log.info("插入：自动填充成功");
        }
        else if (value == OperationType.UPDATE){
            // 单独为每个字段 try-catch，避免一个字段失败导致整体失败
             // 对数据判空


            try {
                Method setUuid = object.getClass().getDeclaredMethod(autoFillConstant.uuid, String.class);
                setUuid.invoke(object, uuid); // 注意：这里第一个参数是实例对象
            } catch (Exception e) {
                log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.uuid);
            }


             try {
                 Method setUpdatedAt = object.getClass().getDeclaredMethod(autoFillConstant.updatedAt, LocalDateTime.class);
                 setUpdatedAt.invoke(object, creatTime);
             } catch (Exception e) {
                 log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.updatedAt);
             }

            try {
                Method setStatus = object.getClass().getDeclaredMethod(autoFillConstant.status, Byte.class);
                setStatus.invoke(object, status);
            } catch (Exception e) {
                log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.status);
            }

             try {
                 Method setOwnerId = object.getClass().getDeclaredMethod(autoFillConstant.ownerId, Long.class);
                 setOwnerId.invoke(object, userId);
             }catch (Exception e){
                 log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.ownerId);
             }

             //家庭成员


             try {
                 Method setUserId = object.getClass().getDeclaredMethod(autoFillConstant.userId, Long.class);
                 setUserId.invoke(object, userId);
             }catch (Exception e){
                 log.warn("字段 [{}] 不存在或设置失败，跳过", autoFillConstant.userId );
             }




            log.info("更新：自动填充成功");
        }


    }




}
